import UIKit
import SnapKit


final class CommentsViewController: UIViewController, Alertable {
    
    // MARK: - Outlets
    
    lazy private var spinner = SpinnerView()

    private lazy var submitBtn: UIButton = {
        let btn = UIButton()
        btn.clipsToBounds = true
        btn.layer.cornerRadius = 15
        btn.setTitle("Комментировать", for: .normal)
        btn.backgroundColor = .blueColor
        btn.setTitleColor(.white, for: .normal)
        btn.titleLabel!.font = UIFont.systemFont(ofSize: 17, weight: .medium)
        return btn
    }()

    private lazy var tableView: UITableView = {
        let table = UITableView()
        table.delegate = self
        table.dataSource = self
        table.register(CommentCell.self, forCellReuseIdentifier: "commentCell")
        table.tableFooterView = UIView()
        table.showsVerticalScrollIndicator = false
        table.separatorColor = .rgb(229, 233, 242)
        return table
    }()
    
    
    private lazy var replyView = ReplyView()
    private lazy var messageField = MessageField()
    
    
    // MARK: - Props

    public var advertID: Int!
    
    private let commentViewModel = CommentViewModel()
    
    private var isLoading: Bool = false {
        didSet {
            isLoading ? spinner.startAnimating() : spinner.stopAnimating()
            view.isUserInteractionEnabled = !isLoading
        }
    }
    
    // comment id на которую хотите ответить
    private var referenceId: Int?
    
    // MARK: - UI Actions
    
    @objc private func goBack (sender: UIBarButtonItem) {
        self.navigationController?.popViewController(animated: true)
    }

    @objc private func onSend (sender: UIButton) {
        if !messageField.getText().isEmpty {
            commentViewModel.sendComment(text: messageField.getText(), replyId: self.referenceId, advert: self.advertID) { (result) in
                switch result {
                case .failure(let err):
                    self.alertError(error: err)
                case .success(_):
                    self.messageField.restartUI()
                    self.referenceId = nil
                    self.tableView.reloadData()
                    self.goBottom()
                }
            }
        }
    }
    
    @objc private func onReplyIconClick (sender: UIButton) {
        self.referenceId = commentViewModel.comments[sender.tag].id
        self.showReplyView(with: "Ответить \(commentViewModel.comments[sender.tag].profile!)")
    }
    
    @objc private func closeReply (sender: UIButton) {
        self.referenceId = nil
        self.hideReplyView()
    }
    
    @objc private func keyboardWillShow(notification: NSNotification) {
        if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
            messageField.transform = CGAffineTransform(translationX: 0, y: -keyboardSize.height + 54)
        }
    }

    @objc private func keyboardWillHide(notification: NSNotification) {
        messageField.transform = .identity
    }
    
    @objc private func screenTap(sender: UITapGestureRecognizer) {
        messageField.hideKeyboard()
    }
    
    // MARK: - Life-Cycle
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.setUpUI()
        self.loadComments(firstTime: true)
    }

    override func viewWillAppear(_ animated: Bool) {
        self.setUpNavBar()
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
    }
    
    override func viewDidDisappear(_ animated: Bool) {
        self.navigationController?.navigationBar.isHidden = true
        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
        NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
    }
}


// MARK: - Methods


extension CommentsViewController {
    
    private func loadComments (firstTime: Bool = false ) {
        self.isLoading = true
        commentViewModel.loadComments(id: advertID) { (result) in
            self.isLoading = false
            
            switch result {
            case .failure(let err):
                self.alertError(error: err)
            case .success(_):
                self.tableView.reloadData()
                if firstTime {
                    if self.commentViewModel.comments.count != 0 {
                        self.tableView.scrollToRow(at: IndexPath(item: self.commentViewModel.comments.count - 1, section: 0), at: .bottom, animated: true)
                    }
                }
            }
        }
    }
    
    private func goBottom () {
        let lastIndex = self.commentViewModel.comments.count == 0 ? nil : self.commentViewModel.comments.count - 1
        if let index = lastIndex {
            let indexPath = IndexPath(row: index, section: 0)
            self.tableView.scrollToRow(at: indexPath, at: .bottom, animated: true)
        }
    }
    
    private func showReplyView (with text: String) {
        if replyView.isHidden {
            replyView.transform = CGAffineTransform(translationX: 0, y: -40)
            replyView.isHidden = false
            replyView.setText(text)
            UIView.animate(withDuration: 0.3, animations: {
                self.replyView.transform = .identity
            })
        } else {
            UIView.animate(withDuration: 0.3, animations: {
                self.replyView.transform = CGAffineTransform(translationX: 0, y: -40)
            }, completion: { _ in
                self.replyView.setText(text)
                UIView.animate(withDuration: 0.3, animations: {
                    self.replyView.transform = .identity
                })
            })
        }
    }
    
    private func hideReplyView () {
        UIView.animate(withDuration: 0.3, animations: {
            self.replyView.transform = CGAffineTransform(translationX: 0, y: -40)
        }, completion: { _ in
            self.replyView.isHidden = true
        })
    }
}


extension CommentsViewController: UITableViewDelegate, UITableViewDataSource {
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return commentViewModel.comments.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "commentCell") as! CommentCell
        cell.comment = commentViewModel.comments[indexPath.row]
        cell.replyButton.tag = indexPath.row
        cell.replyButton.addTarget(self, action: #selector(onReplyIconClick(sender:)), for: .touchUpInside)
        return cell
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return UITableView.automaticDimension
    }
    
    func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
        if scrollView.contentOffset.y <= 0 {
            if commentViewModel.nextURL != nil {
                self.loadComments()
            }
        }
    }
    
}


// MARK: - UI

extension CommentsViewController {
    
    private func setUpUI () {
        view.addSubview(tableView)
        view.addSubview(messageField)
        view.addSubview(spinner)
        view.addSubview(replyView)
        
        replyView.isHidden = true
        let tap = UITapGestureRecognizer(target: self, action: #selector(screenTap(sender:)))
        view.addGestureRecognizer(tap)
        
        messageField.sendButton.addTarget(self, action: #selector(onSend(sender:)), for: .touchUpInside)
        replyView.closeBtn.addTarget(self, action: #selector(closeReply(sender:)), for: .touchUpInside)
        
        addConstraints()
    }
    
    private func addConstraints () {
        messageField.snp.makeConstraints { (make) in
            make.leading.trailing.equalToSuperview()
            make.bottom.equalTo(view.safeAreaLayoutGuide)
        }
        tableView.snp.makeConstraints { (make) in
            make.top.equalTo(view.safeAreaLayoutGuide)
            make.leading.trailing.equalToSuperview()
            make.bottom.equalTo(messageField.snp.top)
        }
        replyView.snp.makeConstraints { (make) in
            make.top.equalTo(view.safeAreaLayoutGuide)
            make.leading.trailing.equalToSuperview()
        }
        spinner.snp.makeConstraints { (make) in
            make.center.equalToSuperview()
        }
    }
    
    private func setUpNavBar () {
        self.navigationController?.navigationBar.isHidden = false
        
        let backIcon = UIImage(named: "cancel")
        let backButton = UIBarButtonItem(image: backIcon, landscapeImagePhone: backIcon, style: .plain, target: self, action: #selector(goBack(sender:)))
        backButton.tintColor = .rgb(132, 146, 166)
        
        self.navigationItem.simpleNavBar(title: "Комментарии", backButton: backButton)
        self.navigationController?.navigationBar.tintColor = .white
        navigationItem.largeTitleDisplayMode = .never
    }
}



final class ReplyView: UIView {
    
    private lazy var titleLbl: UILabel = {
        let lbl = UILabel()
        lbl.font = .systemFont(ofSize: 16)
        lbl.textColor = .white
        lbl.numberOfLines = 0
        return lbl
    }()
    
    lazy var closeBtn: UIButton = {
        let btn = UIButton()
        btn.setImage(UIImage(named: "dismiss"), for: .normal)
        return btn
    }()
    
    init () {
        super.init(frame: .zero)
        self.backgroundColor = .darkBlueColor
        self.addSubview(titleLbl)
        self.addSubview(closeBtn)
        
        titleLbl.snp.makeConstraints { (make) in
            make.top.bottom.equalToSuperview().inset(8)
            make.height.equalTo(20)
            make.leading.equalToSuperview().inset(16)
            make.trailing.equalTo(closeBtn.snp.leading).offset(-8)
        }
        closeBtn.snp.makeConstraints { (make) in
            make.width.height.equalTo(12)
            make.trailing.equalToSuperview().inset(16)
            make.centerY.equalToSuperview()
        }
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    public func setText(_ text: String) {
        self.titleLbl.text = text
    }
}
